from flask import current_app
from flask import g
from flask_restful import Resource, inputs
from flask_restful.reqparse import RequestParser
from sqlalchemy.exc import IntegrityError

from models.news import Comment, CommentLiking
from toutiao import db
from toutiao.utils.decorators import loginrequired
from . import constant
from cache.comment import ArticleCommentsCache, CommentCache, ArticleCommentsReplyCache, UserCommentLikingCache
from cache.statistic import CommentReplyCountStorage


# 发表评论
class CommentsResource(Resource):

    method_decorators = {
        'post': [loginrequired]
    }

    def post(self):
        """发表评论"""
        user_id = g.user_id

        # 接收参数, 校验参数
        parser = RequestParser()
        parser.add_argument('target', location='json', required=True)
        parser.add_argument('content', location='json', required=True)
        parser.add_argument('art_id', type=int, location='json')
        args = parser.parse_args()
        article_id = args.get('target')
        content = args.get('content')
        art_id = args.get('art_id')

        # 把数据保存到到数据库
        comment = Comment()
        comment.article_id = article_id
        comment.user_id = user_id
        comment.content = content

        if not art_id:
            try:
                db.session.add(comment)
                db.session.commit()
            except Exception as e:
                current_app.logger.error(e)
            else:
                # 缓存到数据库
                ArticleCommentsCache(article_id).add(comment)
                CommentCache(comment.id).save(comment)

        else:
            # 如果传入art_id，则表示为回复评论
            comment.article_id = art_id
            comment.parent_id = article_id

            # 统计回复评论数,进行缓存
            CommentReplyCountStorage.incr(article_id)

            try:
                db.session.add(comment)
                db.session.commit()
            except Exception as e:
                current_app.logger.error(e)
            else:
                ArticleCommentsReplyCache(article_id).add(comment)
                CommentCache(comment.id).save(comment)

        # 返回响应
        return {"com_id": comment.id, "target": comment.article_id}

    def get(self):
        """获取品论列表"""
        # 接收参数,检验参数
        """
        type(query)	    str	是	评论类型，a表示文章评论 c表示回复评论
        source(query)	int	是	文章id或者评论id
        offset(query)	int	否	获取评论数据的偏移量
        limit(query)	int	否	评论条数
        """
        parser = RequestParser()
        parser.add_argument('type', location='args', required=True)
        parser.add_argument('source', location='args', required=True)
        parser.add_argument('offset', location='args', type=int)
        parser.add_argument('limit', location='args', type=inputs.int_range(constant.DEFAULT_COMMENT_PER_PAGE_MIN,
                                                                            constant.DEFAULT_COMMENT_PER_PAGE_MAX, 'limit'))

        args = parser.parse_args()

        type = args.get('type')
        source = args.get('source')
        offset = args.get('offset')
        limit = args.get('limit') if args.get('limit') is not None else constant.DEFAULT_COMMENT_PER_PAGE_MIN

        # 查询所有评论
        # 根据type类型来查询评论，(文章id,评论状态，回复为空),按照id降序
        # if type == 'a':
        #     comments = Comment.query.filter(Comment.article_id == source,
        #                                     Comment.status == Comment.STATUS.APPROVED,
        #                                     Comment.parent_id == None).order_by(Comment.id.desc()).all()
        # else:
        #     comments = Comment.query.filter(Comment.article_id == source,
        #                                     Comment.status == Comment.STATUS.APPROVED,
        #                                     Comment.parent_id == None).order_by(Comment.id.desc()).all()
        #
        # # 给数据分页
        # # 初始化需要返回的变量
        # total_count = len(comments)     # 评论总数
        # page_comments = []              # 指定分页的数据
        # end_id = None                   # 所有评论的最后一个的创建时间戳
        # last_id = None                  # 当前分页的最后一条的创建时间戳
        # item_count = 0                  # 计数器
        # page_last_comment = None        # 来记录分页中最后一条记录的对象
        #
        # # 构造page_comments
        # for comment in comments:
        #
        #     # 给每一条评论创建时间戳
        #     score = comment.ctime.timestamp()
        #     # （（判断前端传的时间戳不为空且当前评论时间戳小于前端传的），或者　前端传的时间戳不为空）并且　每页获取数据小于等于前端要求数量
        #     if ((offset is not None and score < offset) or offset is None) and item_count < limit:
        #         page_comments.append({
        #             'com_id': comment.id,
        #             'aut_id': comment.user.id,
        #             'aut_name': comment.user.name,
        #             'aut_photo': comment.user.profile_photo,
        #             'pubdate': comment.ctime.strftime('%Y-%m-%d %H:%M:%S'),
        #             'content': comment.content,
        #             'is_top': comment.is_top,
        #             'is_liking': False,
        #             'reply_count': 0
        #         })
        #
        #         item_count += 1
        #         # 每页最后一个评论的时间戳
        #         page_last_comment = comment
        #
        # # 获取end_id last_id
        # if total_count > 0:
        #     end_id = comments[-1].ctime.timestamp()
        #     last_id = page_last_comment.ctime.timestamp() if page_last_comment is not None else None
        if type == 'a':
            # 发表评论
            total_count, end_id, last_id, page_comments_ids = ArticleCommentsCache(source).get_page(offset, limit)

            page_comments = []
            for page_comments_id in page_comments_ids:
                c = CommentCache(page_comments_id).get()

                # 判断是否点赞
                is_liking = UserCommentLikingCache(g.user_id).user_liking_comment(c['com_id'])
                c['is_liking'] = is_liking

                # 获取回复总数量
                reply_count = CommentReplyCountStorage.get(c['com_id'])
                c['reply_count'] = reply_count

                page_comments.append(c)
        else:
            # 回复评论
            # 查询所有回复评论，评论id，评论状态
            # comments = Comment.query.filter(Comment.parent_id == source,
            #                                 Comment.status == Comment.STATUS.APPROVED).order_by(Comment.id.desc()).all()
            #
            # # 给数据分页
            # # 初始化要返回的数据
            # total_count = len(comments)  # 回复评论总数
            # end_id = None  # 最后一条评论的时间戳
            # last_id = None  # 分页最后一条评论的时间戳
            # item_count = 0  # 计数器
            # page_last_comment = None  # 来记录分页中最后一条记录的对象
            #
            # # 构造分页数据
            # page_comments = []
            # for comment in comments:
            #     # 给每一条评论加上时间戳
            #     score = comment.ctime.timestamp()
            #     # 判断offset是否存在
            #     if ((offset is not None and offset < score) or offset is None) and item_count < limit:
            #         page_comments.append({
            #             'com_id': comment.id,
            #             'aut_id': comment.user.id,
            #             'aut_name': comment.user.name,
            #             'aut_photo': comment.user.profile_photo,
            #             'pubdate': comment.ctime.strftime('%Y-%m-%d %H:%M:%S'),
            #             'content': comment.content,
            #             'is_top': comment.is_top,
            #             'is_liking': False,
            #             'reply_count': 0
            #         })
            #         item_count += 1
            #         page_last_comment = comment
            #
            # # 如果有评论数据，则获取end_id 和　last_id
            # if total_count:
            #     end_id = comments[-1].ctime.timestamp()
            #     last_id = page_last_comment.ctime.timestamp() if page_last_comment else None
            total_count, end_id, last_id, page_comments_ids = ArticleCommentsReplyCache(source).get_page(offset, limit)

            page_comments = []
            for page_comments_id in page_comments_ids:
                c = CommentCache(page_comments_id).get()

                # 判断是否点赞
                is_liking = UserCommentLikingCache(g.user_id).user_liking_comment(c['com_id'])
                c['is_liking'] = is_liking

                page_comments.append(c)

        # 响应结果
        return {
            "total_count": total_count,
            "end_id": end_id,  # 最后一条评论的id, 前端用于判断是否剩余评论, 无值返回None
            "last_id": last_id,  # 本次请求最后一条评论的id, 作为下次请求的offset, 无值返回None
            "results": page_comments  # 分页评论
        }


# 评论点赞
class CommentLikingResource(Resource):
    """评论点赞"""

    method_decorators = [loginrequired]

    def post(self):

        # 接收，检验参数,评论id或回复id
        parser = RequestParser()
        parser.add_argument('target', location='json', required=True, type=int)
        args = parser.parse_args()
        target = args.get('target')

        # 保存到数据库
        try:
            comment_liking = CommentLiking(user_id=g.user_id, comment_id=target, is_deleted=False)
            db.session.add(comment_liking)
            db.session.commit()
        except IntegrityError:
            db.session.rollback()
            CommentLiking.query.filter(CommentLiking.user_id == g.user_id,
                                       CommentLiking.comment_id == target,
                                       CommentLiking.is_deleted == True).update({'is_deleted': False})
            db.session.commit()

        # 缓存点赞
        UserCommentLikingCache(g.user_id).add(target)

        return {'target': target}, 201